package util;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Logger;

/**
 * 一个简陋的连接池的实现
 * 连接超时没做
 * @author Administrator
 *
 */
public class ConnectionPool {
	private static String driverClass;
	private static String url;
	private static String username;
	private static String password;
	
	private static int initConn;//初始化时的连接数
	private static int maxConn;//最大连接数
	private static List<Connection> pool = new ArrayList<Connection>();
	private static List<Boolean> state = new ArrayList<Boolean>();//数据库连接的状态，true：可用，false：不可用
	
	private static Logger log = Logger.getLogger(ConnectionPool.class);
	
	/**
	 * 1. 加载数据库配置文件db.properties，并读取
	 * 2. 建立initConn数量的连接
	 */
	static {
		try {
			//Properties类表示了一个持久的属性集，Properties可保存在流中或从流中加载
			Properties prop = new Properties();
			//ClassLoader（抽象类）的getResourceAsStream()方法会返回读取指定资源的输入流
			InputStream is = ConnectionPool.class.getClassLoader().getResourceAsStream("db.properties");
			if (is == null) {
				log.error("configuration file db.properties is not found...");
			}
			prop.load(is);
			driverClass = prop.getProperty("driverClass");
			url = prop.getProperty("url");
			username = prop.getProperty("username");
			password = prop.getProperty("password");
			initConn = prop.getProperty("initConn") == null ? 5 : Integer.parseInt(prop.getProperty("initConn"));
			maxConn = prop.getProperty("maxConn") == null ? 10 : Integer.parseInt(prop.getProperty("maxConn"));
			Class.forName(driverClass);
			
			//建立initConn数量的连接
			for (int i = 0; i < initConn; i++) {
				Connection conn = DriverManager.getConnection(url, username, password);
				pool.add(conn);
				state.add(Boolean.TRUE);
			}
			if (log.isDebugEnabled()) {
				log.debug("Initialize " + initConn + " connections:" + getAllConnections(Boolean.TRUE));
			}
		} catch(ClassNotFoundException e){
			log.error("Driver class " + e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private ConnectionPool(){
		
	}
	
	/**
	 * 获取连接
	 * @return
	 */
	public static synchronized Connection getConnection() {
		for (int i = 0; i < state.size(); i++) {
			if (state.get(i).booleanValue()) {
				state.remove(i);
				state.add(i, Boolean.FALSE);
				if (log.isDebugEnabled()) {
					log.debug("connection " + pool.get(i).toString() + " is in use...");
					log.debug("All connections are:" + getAllConnections(null));
					log.debug("Free connections are:" + getAllConnections(Boolean.TRUE));
				}
				return pool.get(i);
			}
		}
		if (pool.size() <= maxConn) {
			Connection conn = null;
			try {
				conn = DriverManager.getConnection(url, username, password);
			} catch (SQLException e) {
				//do nothing
			}
			pool.add(conn);
			state.add(Boolean.FALSE);
			if (log.isDebugEnabled()) {
				log.debug("connection " + conn.toString() + " is in use...");
				log.debug("All connections are:" + getAllConnections(null));
				log.debug("Free connections are:" + getAllConnections(Boolean.TRUE));
			}
			return conn;
		} else {
			log.error("the number of connection surpasses the max connection...");
		}
		return null;
	}
	
	
	
	/**
	 * 查询当前已经建立的所有连接
	 * @param isFree 查询空闲连接还是已用连接
	 * @return
	 */
	private static String getAllConnections(Boolean isFree){
		StringBuffer sb = new StringBuffer();
		if (isFree == null) {//查询当前已经建立的所有连接
			for (int i = 0; i < pool.size(); i++) {
				sb.append(pool.get(i).toString() + ",");
			}
		} else if (isFree.booleanValue()) {//查询当前已经建立的所有空闲连接
			for (int i = 0; i < state.size(); i++) {
				if (state.get(i).booleanValue()) {
					sb.append(pool.get(i).toString() + ",");
				}
			}
		} else if (!isFree.booleanValue()) {//查询当前已经建立的所有非空闲连接
			for (int i = 0; i < state.size(); i++) {
				if (!state.get(i).booleanValue()) {
					sb.append(pool.get(i).toString() + ",");
				}
			}
		}
		return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1).replaceAll("com.mysql.jdbc.JDBC4Connection", "");
	}
	
	/**
	 * 关闭连接，其实并不是真正地关闭连接，只是将连接归还到连接池
	 * @param conn
	 */
	public static void closeConnection(Connection conn){
		int index = pool.indexOf(conn);
		state.remove(index);
		state.add(index, Boolean.TRUE);
		if (log.isDebugEnabled()) {
			log.debug("Connection " + conn + " is released...");
			log.debug("All connections are:" + getAllConnections(null));
			log.debug("Free connections are:" + getAllConnections(Boolean.TRUE));
		}
	}
}
